package net.nio;

import lombok.Data;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * @author 王霄
 * @date 2021/8/27 22:37
 */
@Data
public class GroupChatServer {
    private Selector selector;
    private ServerSocketChannel serverSocketChannel;
    private static final int port = 6666;

    public void init() {
        try {
            this.selector = Selector.open();
            this.serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(port));
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void listen() {
        try {
            while (true) {
                if (selector.select(2000) > 0) {
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> iterator = selectionKeys.iterator();
                    while (iterator.hasNext()) {
                        SelectionKey selectionKey = iterator.next();
                        //监听连接事件
                        if (selectionKey.isAcceptable()) {
                            SocketChannel channel = serverSocketChannel.accept();
                            channel.configureBlocking(false);
                            channel.register(selector, SelectionKey.OP_READ);
                            System.out.println(channel.getRemoteAddress() + " 上线了 ");
                        }
                        //监听读取事件
                        if (selectionKey.isReadable()) {
                            SocketChannel channel = null;
                            String msg = null;
                            try {
                                channel = (SocketChannel) selectionKey.channel();
                                ByteBuffer buffer = ByteBuffer.allocate(1024);
                                if (channel.read(buffer) > 0) {
                                    msg = new String(buffer.array());
                                    System.out.println(msg);
                                }

                                //转发数据
                                Set<SelectionKey> keys = selector.keys();
                                for (SelectionKey key : keys) {
                                    Channel target = key.channel();
                                    if (target instanceof SocketChannel targetChannel && target != channel) {
                                        targetChannel.write(ByteBuffer.wrap(msg.getBytes()));
                                    }
                                }
                            } catch (IOException e) {
                                System.out.println(channel.getRemoteAddress() + " 离线了 ");
                                selectionKey.channel();
                                channel.close();
                            }

                        }
                        iterator.remove();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                serverSocketChannel.close();
                selector.close();
            } catch (Exception ignored) {
            }
        }
    }

    public static void main(String[] args) {
        GroupChatServer server = new GroupChatServer();
        server.init();
        server.listen();
    }
}
